package com.seecen.utils;

import cn.hutool.core.util.ObjectUtil;
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.security.Key;
import java.util.Date;

@Slf4j
@Data
@Component
@ConfigurationProperties(prefix = "jwt.token")
public class JwtHelper {

    // token的失效时间（分钟）
    private long tokenExpiration;
    // 私钥（建议长度至少 32 位，否则会报密钥长度不足错误）
    private String tokenSingKey;

    // 生成签名密钥（新版推荐使用 Keys.hmacShaKeyFor() 处理密钥）
    private Key getSigningKey() {
        // 将字符串密钥转换为符合 HS512 算法要求的密钥对象
        byte[] keyBytes = tokenSingKey.getBytes();
        return Keys.hmacShaKeyFor(keyBytes);
    }

    // 生成token
    public String createToken(Long userId) {
        String token = Jwts.builder()
                .setSubject("HHYY-USER") // 设置主题
                .setExpiration(new Date(System.currentTimeMillis() + tokenExpiration * 1000 * 60)) // 过期时间
                .claim("userId", userId) // 自定义载荷
                .signWith(getSigningKey(), SignatureAlgorithm.HS512) // 签名算法+密钥（新版参数顺序调整）
                .compressWith(CompressionCodecs.GZIP) // 压缩
                .compact();
        log.info("生成的token = {}", token);
        return token;
    }

    // 解析token获取用户ID
    public Long getUserId(String token) {
        if (ObjectUtil.isEmpty(token)) {
            return null;
        }
        try {
            // 新版解析逻辑：parserBuilder() -> 设置密钥 -> build() -> 解析
            Jws<Claims> claimsJws = Jwts.parser()
                    .setSigningKey(getSigningKey()) // 使用相同的签名密钥
                    .build() // 构建解析器
                    .parseClaimsJws(token); // 解析token

            Claims claims = claimsJws.getBody();
            // 注意：如果存入的是Long类型，直接强转为Long（避免Integer范围问题）
            Long userId = claims.get("userId", Long.class);
            log.info("解析到的userId = {}", userId);
            return userId;
        } catch (JwtException e) {
            log.error("token解析失败", e);
            return null;
        }
    }

    // 判断token是否过期
    public boolean isExpiration(String token) {
        if (ObjectUtil.isEmpty(token)) {
            return true; // 空token视为过期
        }
        try {
            Date expiration = Jwts.parser()
                    .setSigningKey(getSigningKey())
                    .build()
                    .parseClaimsJws(token)
                    .getBody()
                    .getExpiration();
            // 过期时间是否在当前时间之前
            return expiration.before(new Date());
        } catch (JwtException e) {
            log.error("token验证失败", e);
            return true; // 解析异常视为过期
        }
    }
}
